package iagovsothello.online.client;
import iagovsothello.ai.Agent;
import iagovsothello.core.*;
import iagovsothello.gui.InfoDialog;
import iagovsothello.gui.NewGameWindow;
import iagovsothello.gui.QuickGameWindow;
import iagovsothello.gui.Square;
import iagovsothello.gui.SquareActionListener;
import iagovsothello.gui.TextAreaCapoAutomatico;
import iagovsothello.logger.Experiment;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;
import java.util.List;

import javax.swing.*;
import javax.swing.border.LineBorder;


/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
/**
 * Interfaccia grafica principale
 */
public class MainWindowClient extends JFrame implements OthelloInterface {
	
	private static final long serialVersionUID = -8091108208016281318L;

	private int dimension = 8;
	
	protected GameState currentState;
	private GameState startingState;
	
	protected Agent player1 = null;
	protected Agent player2 = null;
	
	private boolean debugMode = false;
	private LinkedList<GameState> history = null;
	private int historyIndex = 0;
	
	private boolean marker = false;
	
	private JLabel labelx61;
	private JLabel labelx71;
	private JLabel labelx51;
	private JLabel labely41;
	private JLabel labely51;
	private JLabel labely61;
	private JLabel labely71;
	private JLabel labelPlayer1;
	private JLabel labelCurrentGamesLeft;
	private JLabel labelGamesLeft;
	private JLabel labelCurrentID;
	private JLabel labelID;
	private JLabel labelCurrentSurname;
	private JLabel labelSurname;
	private JLabel labelCurrentName;
	private JLabel labelName;
	private TextAreaCapoAutomatico textAreaRules;
	private JScrollPane scrollPaneRules;
	private JMenuItem menuItemLoadExperiment;
	private JMenuItem menuItemQuickGame;
	private JCheckBoxMenuItem checkBoxMenuItemMarker;
	private JCheckBoxMenuItem checkBoxMenuItemCoordinates;
	private JMenuItem menuItemExperiments;
	private JMenu menuOptions;
	private JLabel labelCurrentTurnNumber;
	private JLabel labelTurnNumber;
	private JLabel labelVictory;
	private JMenuItem menuItemAbout;
	private JLabel labelCurrentPlayer;
	private JLabel labelPlayer2Points;
	private JLabel labelPlayer1Points;
	private JLabel labelTurn;
	private JPanel panelPoints;
	private JLabel labelPlayer2;
	private JMenuItem menuItemExit;
	private JLabel labelx32;
	private JLabel labelx02;
	private JLabel labelx12;
	private JLabel labelx22;
	private JLabel labelx42;
	private JLabel labely02;
	private JLabel labely12;
	private JLabel labely22;
	private JLabel labely32;
	private JLabel labely42;
	private JLabel labely52;
	private JLabel labely62;
	private JLabel labely72;
	private JLabel labely01;
	private JLabel labely11;
	private JLabel labely21;
	private JLabel labely31;
	private JLabel labelx52;
	private JLabel labelx62;
	private JLabel labelx72;
	private JLabel labelx41;
	private JLabel labelx31;
	private JLabel labelx21;
	private JLabel labelx11;
	private JLabel labelx01;
	
	private JPanel infoPanel;
	private JPanel grid;
	
	private JMenuBar menuBar;
	private JMenu menuHelp;
	private JMenu menuInstruments;
	private JMenu menuFile;
	
	private Square[][] table;
	
	private Socket socket;
	private String addressIPServer;//sulla macchina dove DOVREBBE andare l'indirizzo sara' 192.168.100.53
	private static int portServer = 7777;

	
	private String gamesLeft;
	private String ID ;
	private String name ;
	private String surname ;

	private int difficultyLevel;
	
	private String securityGameCode;
	
	public static void main(String[] args) 
	{
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				MainWindowClient inst = new MainWindowClient();
			//	inst.disableMenuItems();
				inst.setLocationRelativeTo(null);
				inst.setVisible(true);
			}
		});
	}
	
	
	
	public MainWindowClient(String gamesLeft, String iD,
			String name, String surname, String serverAddress) throws HeadlessException {
		super();
		this.gamesLeft = gamesLeft;
		ID = iD;
		this.name = name;
		this.surname = surname;
		difficultyLevel = -1;
		currentState = null;
		addressIPServer = serverAddress;
		initGUI();
		updateCoordinatesLabels();
		updateMarker();

	}

	public void setDifficultyLevel(int difficultyLevel) {
		this.difficultyLevel = difficultyLevel;
	}



	public MainWindowClient() 
	{
		super();
		currentState = null;
		initGUI();
		updateCoordinatesLabels();
		updateMarker();
		gamesLeft = null;
	}
	
	private void initGUI() 
	{
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		GridBagLayout thisLayout = new GridBagLayout();
		thisLayout.rowWeights = new double[] {0.1, 0.0};
		thisLayout.rowHeights = new int[] {7, 20};
		thisLayout.columnWeights = new double[] {0.1, 0.0};
		thisLayout.columnWidths = new int[] {7, 315};
		getContentPane().setLayout(thisLayout);
		this.setTitle("IAgoVSOthello");
		this.setResizable(false);
		getContentPane().setBackground(new java.awt.Color(192,192,192));

		grid = new JPanel();
		GridBagLayout gridLayout = new GridBagLayout();
		gridLayout.rowWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1};
		gridLayout.rowHeights = new int[] {50, 30, 50, 50, 50, 50, 50, 50, 50, 50, 30, 0};
		gridLayout.columnWeights = new double[] {0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1};
		gridLayout.columnWidths = new int[] {0, 30, 50, 50, 50, 50, 50, 50, 50, 50, 30, 0};
		grid.setLayout(gridLayout);
		getContentPane().add(grid, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
		grid.setBackground(new java.awt.Color(192,192,192));

		labelx01 = new JLabel();
		grid.add(labelx01, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx01.setText("0");

		labelx11 = new JLabel();
		grid.add(labelx11, new GridBagConstraints(3, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx11.setText("1");

		labelx21 = new JLabel();
		grid.add(labelx21, new GridBagConstraints(4, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx21.setText("2");

		labelx31 = new JLabel();
		grid.add(labelx31, new GridBagConstraints(5, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx31.setText("3");

		labelx41 = new JLabel();
		grid.add(labelx41, new GridBagConstraints(6, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx41.setText("4");

		labelx51 = new JLabel();
		grid.add(labelx51, new GridBagConstraints(7, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx51.setText("5");

		labelx61 = new JLabel();
		grid.add(labelx61, new GridBagConstraints(8, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx61.setText("6");

		labelx71 = new JLabel();
		grid.add(labelx71, new GridBagConstraints(9, 1, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx71.setText("7");

		labelx02 = new JLabel();
		grid.add(labelx02, new GridBagConstraints(2, 10, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx02.setText("0");

		labelx12 = new JLabel();
		grid.add(labelx12, new GridBagConstraints(3, 10, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx12.setText("1");

		labelx22 = new JLabel();
		grid.add(labelx22, new GridBagConstraints(4, 10, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx22.setText("2");

		labelx32 = new JLabel();
		grid.add(labelx32, new GridBagConstraints(5, 10, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx32.setText("3");

		labelx42 = new JLabel();
		grid.add(labelx42, new GridBagConstraints(6, 10, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx42.setText("4");

		labelx52 = new JLabel();
		grid.add(labelx52, new GridBagConstraints(7, 10, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx52.setText("5");

		labelx62 = new JLabel();
		grid.add(labelx62, new GridBagConstraints(8, 10, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx62.setText("6");

		labelx72 = new JLabel();
		grid.add(labelx72, new GridBagConstraints(9, 10, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelx72.setText("7");

		labely01 = new JLabel();
		grid.add(labely01, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
		labely01.setText("0");

		labely11 = new JLabel();
		grid.add(labely11, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
		labely11.setText("1");

		labely21 = new JLabel();
		grid.add(labely21, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
		labely21.setText("2");

		labely31 = new JLabel();
		grid.add(labely31, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
		labely31.setText("3");

		labely41 = new JLabel();
		grid.add(labely41, new GridBagConstraints(1, 6, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
		labely41.setText("4");

		labely51 = new JLabel();
		grid.add(labely51, new GridBagConstraints(1, 7, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
		labely51.setText("5");

		labely61 = new JLabel();
		grid.add(labely61, new GridBagConstraints(1, 8, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
		labely61.setText("6");

		labely71 = new JLabel();
		grid.add(labely71, new GridBagConstraints(1, 9, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
		labely71.setText("7");

		labely02 = new JLabel();
		grid.add(labely02, new GridBagConstraints(10, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
		labely02.setText("0");

		labely12 = new JLabel();
		grid.add(labely12, new GridBagConstraints(10, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
		labely12.setText("1");

		labely22 = new JLabel();
		grid.add(labely22, new GridBagConstraints(10, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
		labely22.setText("2");

		labely32 = new JLabel();
		grid.add(labely32, new GridBagConstraints(10, 5, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
		labely32.setText("3");

		labely42 = new JLabel();
		grid.add(labely42, new GridBagConstraints(10, 6, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
		labely42.setText("4");

		labely52 = new JLabel();
		grid.add(labely52, new GridBagConstraints(10, 7, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
		labely52.setText("5");

		labely62 = new JLabel();
		grid.add(labely62, new GridBagConstraints(10, 8, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
		labely62.setText("6");

		labely72 = new JLabel();
		grid.add(labely72, new GridBagConstraints(10, 9, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
		{
			labelVictory = new JLabel();
			grid.add(labelVictory, new GridBagConstraints(2, 0, 8, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelVictory.setFont(new java.awt.Font("Segoe UI",0,24));
		}
		labely72.setText("7");

		initTable();

		infoPanel = new JPanel();
		GridBagLayout infoPanelLayout = new GridBagLayout();
		getContentPane().add(infoPanel, new GridBagConstraints(1, 0, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0));
		infoPanel.setBorder(new LineBorder(new java.awt.Color(0,0,0), 1, false));
		infoPanelLayout.rowWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0};
		infoPanelLayout.rowHeights = new int[] {27, 25, 21, 25, 20, 30, 65, 80, 20, 80, 81};
		infoPanelLayout.columnWeights = new double[] {0.0, 0.0, 0.1};
		infoPanelLayout.columnWidths = new int[] {27, 98, 7};
		infoPanel.setLayout(infoPanelLayout);
		infoPanel.setBackground(new java.awt.Color(192,192,192));

		panelPoints = new JPanel();
		GridBagLayout panelPointsLayout = new GridBagLayout();
		infoPanel.add(panelPoints, new GridBagConstraints(0, 6, 3, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0));
		panelPoints.setBorder(BorderFactory.createTitledBorder(new LineBorder(Color.BLACK),"Punteggio"));
		panelPointsLayout.rowWeights = new double[] {0.1, 0.1};
		panelPointsLayout.rowHeights = new int[] {7, 7};
		panelPointsLayout.columnWeights = new double[] {0.0, 0.1};
		panelPointsLayout.columnWidths = new int[] {145, 7};
		panelPoints.setLayout(panelPointsLayout);
		panelPoints.setBackground(new java.awt.Color(192,192,192));

		labelPlayer2 = new JLabel();
		panelPoints.add(labelPlayer2, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelPlayer2.setText("Nero:");
		labelPlayer2.setFont(new java.awt.Font("Dialog",1,16));

		labelPlayer1 = new JLabel();
		panelPoints.add(labelPlayer1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
		labelPlayer1.setText("Bianco:");
		labelPlayer1.setForeground(new java.awt.Color(255,255,255));
		labelPlayer1.setFont(new java.awt.Font("Dialog",1,16));

		labelPlayer1Points = new JLabel();
		panelPoints.add(labelPlayer1Points, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 4, 0, 0), 0, 0));
		labelPlayer1Points.setText("0");
		labelPlayer1Points.setForeground(new java.awt.Color(255,255,255));
		labelPlayer1Points.setFont(new java.awt.Font("Dialog",1,16));

		labelPlayer2Points = new JLabel();
		panelPoints.add(labelPlayer2Points, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 4, 0, 0), 0, 0));
		labelPlayer2Points.setText("0");
		labelPlayer2Points.setFont(new java.awt.Font("Dialog",1,16));

		labelTurn = new JLabel();
		infoPanel.add(labelTurn, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 2), 0, 0));
		labelTurn.setText("Tocca a:");

		labelCurrentPlayer = new JLabel();
		infoPanel.add(labelCurrentPlayer, new GridBagConstraints(1, 4, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0));
		labelCurrentPlayer.setForeground(Color.BLACK);
		labelCurrentPlayer.setText("Nessuno");
		labelCurrentPlayer.setFont(new java.awt.Font("Dialog",1,14));

		labelTurnNumber = new JLabel();
		infoPanel.add(labelTurnNumber, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 2), 0, 0));
		labelTurnNumber.setText("Turno #:");

		labelCurrentTurnNumber = new JLabel();
		infoPanel.add(labelCurrentTurnNumber, new GridBagConstraints(1, 5, 2, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 2, 0, 0), 0, 0));
		labelCurrentTurnNumber.setText("0");

		GridBagLayout panelDebugLayout = new GridBagLayout();
		{
			scrollPaneRules = new JScrollPane();
			infoPanel.add(scrollPaneRules, new GridBagConstraints(0, 7, 3, 4, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0));
			{
				textAreaRules = new TextAreaCapoAutomatico(43);
				scrollPaneRules.setViewportView(textAreaRules);
				textAreaRules.setBackground(new java.awt.Color(255,255,255));
				setRulesText();
				textAreaRules.setCaretPosition(0);
				textAreaRules.setEditable(false);

			}
		}
		{
			labelName = new JLabel();
			infoPanel.add(labelName, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelName.setText("Nome");
			labelName.setFont(new java.awt.Font("Dialog",2,12));
		}
		{
			labelCurrentName = new JLabel();
			infoPanel.add(labelCurrentName, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelCurrentName.setText(name);
		}
		{
			labelSurname = new JLabel();
			infoPanel.add(labelSurname, new GridBagConstraints(0, 1, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelSurname.setText("Cognome");
			labelSurname.setFont(new java.awt.Font("Dialog",2,12));
		}
		{
			labelCurrentSurname = new JLabel();
			infoPanel.add(labelCurrentSurname, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelCurrentSurname.setText(surname);
		}
		{
			labelID = new JLabel();
			infoPanel.add(labelID, new GridBagConstraints(0, 2, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelID.setText("Matricola");
			labelID.setFont(new java.awt.Font("Dialog",2,12));
		}
		{
			labelCurrentID = new JLabel();
			infoPanel.add(labelCurrentID, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelCurrentID.setText(ID);
		}
		{
			labelGamesLeft = new JLabel();
			infoPanel.add(labelGamesLeft, new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelGamesLeft.setText("Partite a disposizione");
			labelGamesLeft.setFont(new java.awt.Font("Dialog",2,12));
		}
		{
			labelCurrentGamesLeft = new JLabel();
			infoPanel.add(labelCurrentGamesLeft, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
			labelCurrentGamesLeft.setText(gamesLeft);

		}

		menuBar = new JMenuBar();
		setJMenuBar(menuBar);
		menuBar.setBackground(new java.awt.Color(255,255,255));
		menuBar.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, new java.awt.Color(0,0,0)));

		menuFile = new JMenu();
		menuBar.add(menuFile);
		menuFile.setText("Start");
		menuFile.setBackground(new java.awt.Color(255,255,255));
		{
			menuItemExperiments = new JMenuItem();
			menuItemExperiments.setText("Esperimenti");
			menuItemExperiments.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					//			experiment();
				}
			});
			
			menuItemLoadExperiment = new JMenuItem();
			menuItemLoadExperiment.setText("Carica e stampa su console esperimento da file");
			menuItemLoadExperiment.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					loadExperiment();
				}
			});
			
			menuOptions = new JMenu();
			menuBar.add(menuOptions);
			menuOptions.setText("Opzioni");
			menuOptions.setBackground(new java.awt.Color(255,255,255));
			
			checkBoxMenuItemCoordinates = new JCheckBoxMenuItem();
			menuOptions.add(checkBoxMenuItemCoordinates);
			checkBoxMenuItemCoordinates.setText("Coordinate numeri/lettere");
			checkBoxMenuItemCoordinates.setSelected(true);
			checkBoxMenuItemCoordinates.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					updateCoordinatesLabels();
				}
			});
			
			checkBoxMenuItemMarker = new JCheckBoxMenuItem();
			menuOptions.add(checkBoxMenuItemMarker);
			checkBoxMenuItemMarker.setText("Marker ultima mossa");
			checkBoxMenuItemMarker.setSelected(true);
			checkBoxMenuItemMarker.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					updateMarker();
				}
			});
			
			menuHelp = new JMenu();
			menuBar.add(menuHelp);
			menuHelp.setText("Aiuto");
			menuHelp.setBackground(new java.awt.Color(255,255,255));
			
			menuItemAbout = new JMenuItem();
			menuHelp.add(menuItemAbout);
			menuItemAbout.setText("Informazioni su...");
			menuItemAbout.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					aboutWindow();
				}
			});
			
			pack();
			this.setSize(850, 600);
		}
		
		menuItemQuickGame = new JMenuItem();
		menuFile.add(menuItemQuickGame);
		menuItemQuickGame.setText("Gioca contro IAgo!");
		menuItemQuickGame.setBounds(108, 43, 76, 21);
		menuItemQuickGame.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				quickGame();
			}
		});

		menuItemExit = new JMenuItem();
		menuFile.add(menuItemExit);
		menuItemExit.setText("Esci");
		menuItemExit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				exit();
			}
		});

		menuInstruments = new JMenu();
		menuBar.add(menuInstruments);
		menuInstruments.setText("Strumenti");
		menuInstruments.setBackground(new java.awt.Color(255,255,255));
		menuInstruments.setEnabled(false);
	}
	
	private void initTable()
	{
		table = new Square[8][8];
		for (int i = 0; i < 8; i++)
		{
			for (int j = 0; j < 8; j++)
			{
					table[i][j] = new Square(new Position(j,i),0);
					table[i][j].addActionListener(new SquareActionListener(this,table[i][j]));
					grid.add(table[i][j],new GridBagConstraints(j+2, i+2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
					table[i][j].setPreferredSize(new Dimension(50,50));
			}
		}
	}
	
	public Agent getCurrentPlayer()
	{
		if (currentState != null)
		{
			if (currentState.getCurrentPlayer() == 1)
				return player1;
			else if (currentState.getCurrentPlayer() == 2)
				return player2;
			else
				return null;
		}
		else
			return null;
	}
	
	public void nextMove()
	{
//		if (currentState.getTurnNumber() == 3)
//		{
//			if (currentState.diagonalOpening())
//				System.out.println("DIAGONALE");
//			if (currentState.perpendicularOpening())
//				System.out.println("PERPENDICOLARE");
//			if (currentState.parallelOpening())
//			System.out.println("PARALLELA");
//		}
		
		Agent currentPlayer = getCurrentPlayer();
//		System.out.println("pos. legali: "+currentState.hasLegalPositions()+", game over: "+currentState.isGameOver());
		
		//se !gameOver, se il giocatore corrente � una AI, in modalit� normale
		if (!currentState.isGameOver() && currentPlayer != null && !debugMode)
		{
	//		menuItemNewGame.setEnabled(false);
	//		menuItemQuickGame.setEnabled(false);
			currentPlayer.nextMove(this, currentState);
		}
		else
		{
		//	menuItemNewGame.setEnabled(true);
			menuItemQuickGame.setEnabled(true);
			if (!currentState.hasLegalPositions() && !currentState.isGameOver())
			{
				setNextMove(null);
				nextMove();
			}
		}
		
	}
	
	public void setNextMove(Position p) 
	{
		boolean stall = false;
		String a = "";
		String b = "";
		if (p == null && (player1 == null || player2 == null) && !currentState.isGameOver())
		{
			stall = true;
			if (currentState.getCurrentPlayer() == 1)
			{
				a = "Bianco";
				b = "Nero";
			}
			else
			{
				a = "Nero";
				b = "Bianco";
			}
		}
		
		//aggiornamento dello stato con la nuova mossa
		currentState.move(p);
		
		//se la modalit� debug � attiva
		if (debugMode && history != null)
		{
			/*se la mossa attualmente visualizzata a schermo non � l'ultima eseguita 
			 * bisogna eliminare tutte le mosse successive da history!*/
			if (historyIndex < history.size()-1)
			{
				int diff = history.size()-1-historyIndex;
				for (int i = 0; i < diff; i++)
				{
					history.removeLast();
				}
			}
			
			//si clona lo stato aggiornato e lo si inserisce in history
			history.add(currentState.clone());
			historyIndex++;
//			System.out.println("move: "+currentState.getTurnNumber()+", size: "+history.size()+", index: "+historyIndex);
		}
		
		if (stall && !currentState.isGameOver())
		{
			JOptionPane.showMessageDialog(this, "Il giocatore corrente ("+a+") non ha mosse legali; tocca di nuovo a "+b, 
					"Stallo", JOptionPane.INFORMATION_MESSAGE);
		}
		
		refreshGameStatus(p);
	}
	
	public void startGame(int dimension, boolean debugMode)
	{
		this.dimension = dimension;
		this.debugMode = debugMode;
		this.startingState = GameState.createStartingState(dimension);
		this.currentState = startingState.clone();
		
	//	panelDebug.setVisible(debugMode);
		if (debugMode)
		{
			history = new LinkedList<GameState>();
			history.add(startingState.clone());
		}
		else
			history = null;
		historyIndex = 0;
		refreshGameStatus(null);
	}
	
	public void startGame(GameState startingState, int dimension, boolean debugMode)
	{
		this.dimension = dimension;
		this.startingState = startingState;
		this.currentState = startingState.clone();
		this.debugMode = debugMode;
		
		
	//	panelDebug.setVisible(debugMode);
		if (debugMode)
		{
			history = new LinkedList<GameState>();
			history.add(startingState.clone());
		}
		else
			history = null;
		historyIndex = 0;
		refreshGameStatus(null);
	}
	
	public void restart()
	{
		if (player1 != null)
			player1 = player1.clone();
		if (player2 != null)
			player2 = player2.clone();
		
		if (debugMode)
		{
			history = new LinkedList<GameState>();
			history.add(startingState.clone());
		}
		else
			history = null;
		historyIndex = 0;
		
		currentState = startingState.clone();
		refreshGameStatus(null);
		nextMove();
	}
	
	public void refreshGameStatus(Position markedPosition)
	{
		List<Position> legalPositions = currentState.getLegalPositions();
		refreshPanel(legalPositions);
		refreshTable(legalPositions,markedPosition);
	}
	
	public void setMark(Position p, boolean mark)
	{
		table[p.getY()][p.getX()].setMark(mark);
	}
	
	private void refreshPanel(List<Position> legalPositions)
	{
		int points1 = currentState.getPoints(1);
		int points2 = currentState.getPoints(2);
		labelPlayer1Points.setText(points1+"");
		labelPlayer2Points.setText(points2+"");
		
		String difficulty = null;
		if(difficultyLevel == 1)
			difficulty = "PRINCIPIANTE";
		else if(difficultyLevel == 2)
			difficulty = "APPRENDISTA";
		else if(difficultyLevel == 3)
			difficulty = "INTERMEDIO";
		else if(difficultyLevel == 4)
			difficulty = "ESPERTO";
		else if(difficultyLevel == 5)
			difficulty = "MOLTO ESPERTO";

		
		if (currentState.getCurrentPlayer() == 1)
		{
			labelCurrentPlayer.setForeground(Color.WHITE);
			if (getCurrentPlayer() != null){
				//labelCurrentPlayer.setText("Bianco ("+getCurrentPlayer()+")");

				labelCurrentPlayer.setText("Bianco (IAgo " + difficulty + ")");
			}
			else
				labelCurrentPlayer.setText("Bianco (umano)");
		}
		else
		{
			labelCurrentPlayer.setForeground(Color.BLACK);
			if (getCurrentPlayer() != null){
				//labelCurrentPlayer.setText("Nero ("+getCurrentPlayer()+")");
				labelCurrentPlayer.setText("Nero (IAgo " + difficulty + ")");
			}			
			else
				labelCurrentPlayer.setText("Nero (umano)");
		}
		labelCurrentTurnNumber.setText(currentState.getTurnNumber()+"");
		if (currentState.isGameOver())
		{
			if (points1 > points2)
			{
				labelVictory.setForeground(Color.WHITE);
				labelVictory.setText("Vittoria: Bianco");
			}
			else if (points1 < points2)
			{
				labelVictory.setForeground(Color.BLACK);
				labelVictory.setText("Vittoria: Nero");
			}
			else
			{
				labelVictory.setForeground(Color.RED);
				labelVictory.setText("Pareggio");
			}
			
			try {
				sendEndGameInfo();
			} catch (UnknownHostException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		else
		{
			labelVictory.setText("");
		}
		/*
		if (debugMode && history != null)
		{
				buttonBack.setEnabled(historyIndex > 0);
				buttonStart.setEnabled(historyIndex > 0);
				buttonForward.setEnabled(historyIndex < history.size()-1);
				buttonEnd.setEnabled(historyIndex < history.size()-1);
				buttonPlay.setEnabled(getCurrentPlayer() != null && !legalPositions.isEmpty());
		}
		*/
	}
	
	private void refreshTable(List<Position> legalPositions, Position markedPosition)
	{
		if (currentState == null)
		{
			for (int i = 0; i < dimension; i++)
			{
				for (int j = 0; j < dimension; j++)
				{
					table[i][j].setStatus(0);
				}
			}
		}
		else
		{
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 8; j++)
				{
					if (i < dimension && j < dimension)
					{
						table[i][j].setStatus(currentState.getSquareStatus(j,i));
						table[i][j].setMark(false);
					}
					else
					{
						table[i][j].setStatus(5);
					}
				}
			}
			
			/* settaggio delle posizioni in cui � ammessa una mossa legale: si fa solo se la lista non � nulla e se
			 * il giocatore attuale � umano (ossia quando getCurrentPlayer() restituisce null)*/
			if (legalPositions != null && getCurrentPlayer() == null)
			{
				for (Position p : legalPositions)
				{
					table[p.getY()][p.getX()].setStatus(currentState.getCurrentPlayer()+2);
				}
			}
		}
		if (marker && markedPosition != null)
		{
			table[markedPosition.getY()][markedPosition.getX()].setMark(true);
		}
		grid.repaint();
	}
	
	private void newGame() 
	{
		NewGameWindow inst = new NewGameWindow(this);
		inst.setAlwaysOnTop(true);
//		inst.setAutoRequestFocus(true);
		inst.setLocationRelativeTo(this);
		inst.setVisible(true);
	}
	
	private void exit() 
	{
		System.exit(0);
	}

	
	private void updateCoordinatesLabels() 
	{
		if (this.checkBoxMenuItemCoordinates.isSelected())
		{
			labelx01.setText("A");
			labelx11.setText("B");
			labelx21.setText("C");
			labelx31.setText("D");
			labelx41.setText("E");
			labelx51.setText("F");
			labelx61.setText("G");
			labelx71.setText("H");
			
			labelx02.setText("A");
			labelx12.setText("B");
			labelx22.setText("C");
			labelx32.setText("D");
			labelx42.setText("E");
			labelx52.setText("F");
			labelx62.setText("G");
			labelx72.setText("H");
			
			labely01.setText("1");
			labely11.setText("2");
			labely21.setText("3");
			labely31.setText("4");
			labely41.setText("5");
			labely51.setText("6");
			labely61.setText("7");
			labely71.setText("8");
			
			labely02.setText("1");
			labely12.setText("2");
			labely22.setText("3");
			labely32.setText("4");
			labely42.setText("5");
			labely52.setText("6");
			labely62.setText("7");
			labely72.setText("8");
		}
		else
		{
			labelx01.setText("0");
			labelx11.setText("1");
			labelx21.setText("2");
			labelx31.setText("3");
			labelx41.setText("4");
			labelx51.setText("5");
			labelx61.setText("6");
			labelx71.setText("7");
			
			labelx02.setText("0");
			labelx12.setText("1");
			labelx22.setText("2");
			labelx32.setText("3");
			labelx42.setText("4");
			labelx52.setText("5");
			labelx62.setText("6");
			labelx72.setText("7");
			
			labely01.setText("0");
			labely11.setText("1");
			labely21.setText("2");
			labely31.setText("3");
			labely41.setText("4");
			labely51.setText("5");
			labely61.setText("6");
			labely71.setText("7");
			
			labely02.setText("0");
			labely12.setText("1");
			labely22.setText("2");
			labely32.setText("3");
			labely42.setText("4");
			labely52.setText("5");
			labely62.setText("6");
			labely72.setText("7");
		}
	}
	
	private void updateMarker() 
	{
		marker = (checkBoxMenuItemMarker.isSelected());
	}
	
	private void aboutWindow()
	{
		InfoDialog inst = new InfoDialog(this);
		inst.setLocationRelativeTo(this);
		inst.setVisible(true);
	}
	
	private void loadExperiment() 
	{
		JFileChooser chooser = new JFileChooser("/");
		int result = chooser.showOpenDialog(this);
		if (result == JFileChooser.APPROVE_OPTION)
		{
			File file = chooser.getSelectedFile();
			try {
				ObjectInputStream st = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));
				try {
					Experiment exp = (Experiment) st.readObject();
					st.close();
					exp.printRecursive();
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void quickGame() 
	{
		QuickGameWindowClient qgw = new QuickGameWindowClient(this);
		qgw.setLocationRelativeTo(this);
		qgw.setAlwaysOnTop(true);
		qgw.setVisible(true);
		qgw.setID(ID);
		qgw.setAddressIPServer(addressIPServer);
	}
	
	//public void disableMenuItems()}
	
	private void setRulesText()
	{
		textAreaRules.setText(
				"REGOLE DI OTHELLO\n\n"+
				"Il primo turno spetta sempre al giocatore nero.\n\n " +
				"Ci si muove alternativamente appoggiando una nuova pedina in una casella vuota in modo da imprigionare, tra la pedina che si sta giocando e quelle del proprio colore gia' presenti "+
				"sulla scacchiera, una o piu' pedine avversarie. Le pedine imprigionate vengono rovesciate e diventano di proprieta' di chi ha eseguito la mossa.\n\n " +
				"E' possibile incastrare le pedine in orizzontale, in verticale e "+
				"in diagonale e, a ogni mossa, si possono rovesciare pedine in una o piu' direzioni.\n\n " +
				"Non e' possibile mettere una pedina in qualunque punto della tavola, ma questa può essere messa solo in quelle posizioni tali che il suo inserimento fa "+
				"rovesciare una o più pedine avversarie;\n\n "+  
				"Si e' costretti a passare il turno nel caso in cui non vi sia alcuna mossa valida.\n\n Quando nessuno dei giocatori ha la possibilita' di muovere o quando l'othelliera e' piena, la partita "+
				"termina e si assegna la vittoria a chi ne ha il maggior numero."
		,true);
	}

	@Override
	public Agent getPlayer1() {
		// TODO Auto-generated method stub
		return player1;
	}

	@Override
	public Agent getPlayer2() {
		// TODO Auto-generated method stub
		return player2;
	}

	@Override
	public void setPlayer1(Agent a) {
		// TODO Auto-generated method stub
		player1 = a;
		
	}

	@Override
	public void setPlayer2(Agent a) {
		// TODO Auto-generated method stub
		player2 = a;
	}
	private void sendEndGameInfo() throws UnknownHostException, IOException{
		
		socket = new Socket(addressIPServer, portServer);

		PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
		BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));

		/*Pacchetto uscita:
		 * end game
		 * ID
		 * codice sicurezza partita
		 * difficolt� (da 1 a 5)
		 * colore giocatore umano (1 bianco, 2 nero)
		 * punteggio umano
		 * punteggio ai
		 */
		
		/*Pacchetto ingresso dal server
		 * ACK
		 * numero di partite rimanenti
		 * 
		 * OPPURE
		 * NACK
		 * codice errore
		 */
		//falofonte!
		int humanColor = 0;
		if(getPlayer1()==null)
			humanColor = 1;
		else
			humanColor = 2;
		
		int humanScore = -1;
		int aiScore = -1;
		
		if(humanColor == 1){
			humanScore = currentState.getPoints(1);
			aiScore = currentState.getPoints(2);
		}
		else if(humanColor == 2){
			humanScore = currentState.getPoints(2);
			aiScore = currentState.getPoints(1);
		}
		
		out.println("endGame");
		out.println(ID);
		out.println(securityGameCode);
		out.println(difficultyLevel);
		out.println(humanColor);
		out.println(humanScore);
		out.println(aiScore);
		out.flush();
		
		String status = in.readLine();
		
		
		if (status.equals("NACK"))
		{
			System.out.println("CLIENT: ricevuto NACK dal server\n");
			String errorCode = in.readLine();
			if(errorCode.equals("2"))
				JOptionPane.showMessageDialog(null, "ATTENZIONE: hai esaurito il numero di partite disponibili!");
			else if(errorCode.equals("3"))
				JOptionPane.showMessageDialog(null, "ATTENZIONE: non sei autorizzato a giocare!");
			else if(errorCode.equals("1"))
				JOptionPane.showMessageDialog(null, "ATTENZIONE: non sei iscritto al torneo!");

		}
		else if (status.equals("ACK")){
			System.out.println("CLIENT: ricevuto ACK dal server dopo la partita\n");
			
			gamesLeft = in.readLine();
			labelCurrentGamesLeft.setText(gamesLeft);
			System.out.println("CLIENT: sono rimaste "+ gamesLeft + "partite\n");

			
		}	
		socket.close();			
		
	}



	public String getSecurityGameCode() {
		return securityGameCode;
	}



	public void setSecurityGameCode(String securityGameCode) {
		this.securityGameCode = securityGameCode;
	}



	public String getGamesLeft() {
		return gamesLeft;
	}



	public void setGamesLeft(String gamesLeft) {
		this.gamesLeft = gamesLeft;
		labelCurrentGamesLeft.setText(gamesLeft);
	}
}
